package com.fau.wmbj.server.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * TODO
 *
 * @author jiawei
 * @version 1.0
 * @datetime 2024/4/22 下午3:59
 */
public class Formula {

    public static final String[] operator = {"==", "!=", "<>", "<=", ">=", "=", "+", "-", ">", "<", "/", "*", "%", "&", "^"};

    public static String functionStrChange(String txt, String type, String rc, String orient, Integer stindex, Integer step) {
        if (StringUtils.equals(StringUtils.substring(txt, 0, 1), "=")) {
            txt = StringUtils.substring(txt, 1);
        }
        String[] funcstack = StringUtils.split(txt, "");
        int i = 0;
        StringBuilder str = new StringBuilder();
        StringBuilder function_str = new StringBuilder();
        List<String> operators = Arrays.asList(operator);
        boolean ispassby = true;
        Map<String, Object> matchConfig = new HashMap<String, Object>() {
            {
                put("bracket", 0);
                put("comma", 0);
                put("squote", 0);
                put("dquote", 0);
            }
        };
        while (i < funcstack.length) {
            String s = funcstack[i];
            int dquote = (int) matchConfig.get("dquote");
            int bracket = (int) matchConfig.get("bracket");
            int squote = (int) matchConfig.get("squote");
            if (StringUtils.equals(s, "(") && dquote == 0) {
                bracket += 1;
                if (str.length() > 0) {
                    function_str.append(str).append("(");
                } else {
                    function_str.append("(");
                }
                str = new StringBuilder();
            } else if (StringUtils.equals(s, ")") && dquote == 0) {
                bracket -= 1;
                function_str.append(functionStrChange(str.toString(), type, rc, orient, stindex, step)).append(")");
                str = new StringBuilder();
            } else if (StringUtils.equals(s, "\"") && squote == 0) {
                if (dquote > 0) {
                    function_str.append(str).append("\"");
                    dquote -= 1;
                    str = new StringBuilder();
                } else {
                    dquote += 1;
                    str.append("\"");
                }
            } else if (StringUtils.equals(s, ",") && dquote == 0) {
                function_str.append(functionStrChange(str.toString(), type, rc, orient, stindex, step)).append(",");
                str = new StringBuilder();
            } else if (StringUtils.equals(s, "&") && dquote == 0) {
                if (str.length() > 0) {
                    function_str.append(functionStrChange(str.toString(), type, rc, orient, stindex, step)).append("&");
                    str = new StringBuilder();
                } else {
                    function_str.append("&");
                }
            } else if (CollectionUtil.contains(operators, s) && dquote == 0) {
                String s_next = "";
                if (i + 1 < funcstack.length) {
                    s_next = funcstack[i + 1];
                }
                int p = i - 1;
                String s_pre = null;
                if (p >= 0) {
                    do {
                        s_pre = funcstack[p--];
                    } while (p >= 0 && StringUtils.equals(s_pre, " "));
                }
                if (CollectionUtil.contains(operators, s + s_next)) {
                    if (str.length() > 0) {
                        function_str.append(functionStrChange(str.toString(), type, rc, orient, stindex, step)).append(s).append(s_next);
                        str = new StringBuilder();
                    } else {
                        function_str.append(s).append(s_next);
                    }
                    i++;
                } else if (ReUtil.isMatch("!/[^0-9]/", s_next) &&
                        StringUtils.equals(s, "-") &&
                        (StringUtils.equals(s_pre, "(") ||
                                s_pre == null || StringUtils.equals(s_pre, ",") ||
                                StringUtils.equals(s_pre, " ") ||
                                CollectionUtil.contains(operators, s_pre))
                ) {
                    str.append(s);
                } else {
                    if (str.length() > 0) {
                        function_str.append(functionStrChange(str.toString(), type, rc, orient, stindex, step)).append(s);
                        str = new StringBuilder();
                    } else {
                        function_str.append(s);
                    }
                }
            } else {
                str.append(s);
            }
            if (i == funcstack.length - 1) {
                if (!StringUtils.contains(str, "!") && isCellData(StringUtils.trim(str.toString()))) {
                    function_str.append(functionStrChange(StringUtils.trim(str.toString()), type, rc, orient, stindex, step));
                } else {
                    function_str.append(StringUtils.trim(str.toString()));
                }
            }
            i++;
        }
        return function_str.toString();
    }

    /**
     * 判断是否为单元格数据
     *
     * @param str 字符串
     */
    public static boolean isCellData(String str) {
        String[] val = StringUtils.split(str, "!");
        String rangetxt = "";
        if (val.length > 1) {
            rangetxt = val[1];
        } else {
            rangetxt = val[0];
        }
        //增加正则判断单元格为字母+数字的格式：如 A1:B3
        String reg_cell = "/^(([a-zA-Z]+)|([$][a-zA-Z]+))(([0-9]+)|([$][0-9]+))$/g";
        //增加正则判断单元格为字母+数字或字母的格式：如 A1:B3，A:A
        String reg_cellRange = "/^(((([a-zA-Z]+)|([$][a-zA-Z]+))(([0-9]+)|([$][0-9]+)))|((([a-zA-Z]+)|([$][a-zA-Z]+))))$/g";
        if (StringUtils.indexOf(rangetxt, ":") > -1) {
            int row = Integer.parseInt(StringUtils.replace(rangetxt, "/[^0-9]/g", "")) - 1;
            int col = ABCatNum(StringUtils.replace(rangetxt, "/[^A-Za-z]/g", ""));
            if (ReUtil.isMatch(reg_cell, rangetxt)) {
                return true;
            } else {
                return false;
            }
        } else {
            reg_cellRange = "/^(((([a-zA-Z]+)|([$][a-zA-Z]+))(([0-9]+)|([$][0-9]+)))|((([a-zA-Z]+)|([$][a-zA-Z]+)))|((([0-9]+)|([$][0-9]+s))))$/g";
            String[] rangetxtArr = StringUtils.split(rangetxt, ":");
            Integer[] row = new Integer[2];

            Integer[] col = new Integer[2];
            row[0] = Integer.parseInt(StringUtils.replace(rangetxtArr[0], "/[^0-9]/g", "")) - 1;
            row[1] = Integer.parseInt(StringUtils.replace(rangetxtArr[1], "/[^0-9]/g", "")) - 1;
            if (row[0] > row[1]) {
                return false;
            }
            col[0] = ABCatNum(StringUtils.replace(rangetxtArr[0], "/[^A-Za-z]/g", ""));
            col[1] = ABCatNum(StringUtils.replace(rangetxtArr[1], "/[^A-Za-z]/g", ""));
            if (col[0] > col[1]) {
                return false;
            }
            if (ReUtil.isMatch(reg_cellRange, rangetxtArr[0]) && ReUtil.isMatch(reg_cellRange, rangetxtArr[1])) {
                return true;
            } else {
                return false;
            }
        }
    }

    /**
     * 列下标  字母转数字
     */
    public static int ABCatNum(String a) {
        int num = 0;
        String[] str = a.toLowerCase().split("");
        int al = str.length;
        int numout = 0;
        int charnum = 0;
        for (int i = 0; i < al; i++) {
            charnum = getCharNumber(str[i]);
            numout += (int) (charnum * Math.pow(26, al - i - 1));
        }
        return numout - 1;
    }

    /**
     * 字母转数字
     *
     * @param c
     */
    public static int getCharNumber(String c) {

        //获取unicode编码
        int unicode = c.charAt(0);
        return unicode - 96;
    }
}
